package com.ray.base.api;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ray.base.builder.MaterialBuilder;
import com.ray.base.builder.MaterialExtendBuilder;
import com.ray.base.builder.MaterialModelBuilder;
import com.ray.base.builder.PropBuilder;
import com.ray.base.check.MaterialCheck;
import com.ray.base.check.MaterialTypeCheck;
import com.ray.base.service.*;
import com.ray.base.table.dto.MaterialQueryDTO;
import com.ray.base.table.dto.MaterialTemplateQueryDTO;
import com.ray.base.table.entity.BaseMaterial;
import com.ray.base.table.entity.BaseMaterialExtend;
import com.ray.base.table.entity.BaseMaterialType;
import com.ray.base.table.params.material.MaterialCreateParams;
import com.ray.base.table.params.material.MaterialEditParams;
import com.ray.base.table.params.material.MaterialQueryParams;
import com.ray.base.table.vo.material.MaterialVO;
import com.ray.base.table.vo.material.PropVO;
import com.ray.system.builder.CommonPageBuilder;
import com.ray.validate.support.utils.ValidateUtil;
import com.ray.woodencreate.annotation.ServiceLog;
import com.ray.woodencreate.beans.LoginUser;
import com.ray.woodencreate.enums.YesOrNoEnum;
import com.ray.woodencreate.exception.BusinessExceptionFactory;
import com.ray.woodencreate.page.CommonPage;
import com.ray.woodencreate.result.MsgCodeConstant;
import com.ray.woodencreate.result.Result;
import com.ray.woodencreate.result.ResultFactory;
import com.ray.woodencreate.util.Assert;
import com.ray.woodencreate.util.LogInUserUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author bo shen
 * @Description: 物料相关服务
 * @Class: MaterialApi
 * @Package com.ray.system.api
 * @date 2020/5/27 11:15
 * @material <p>Ray快速开发平台</p>
 * @updateRecord time(修改时间)  author(修改人)   desc(修改内容)
 */
@Service
@Slf4j
public class MaterialApi {

    @Autowired
    private BaseMaterialService baseMaterialService;
    @Autowired
    private BaseMaterialExtendService baseMaterialExtendService;
    @Autowired
    private BaseMaterialTemplateService baseMaterialTemplateService;
    @Autowired
    private BaseMaterialTypeService baseMaterialTypeService;
    @Autowired
    private BaseMaterialModelService materialModelService;


    /**
     * 查询物料列表信息 分页  非删除的
     *
     * @param queryParams
     * @return
     */
    @ServiceLog(name = "查询原料-分页")
    public Result<IPage<MaterialVO>> pageMaterials(CommonPage<MaterialQueryParams, Page<MaterialVO>> queryParams) {
        Assert.notNull(queryParams, "参数[queryParams]不存在");
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        Map<String,BaseMaterialType> materialTypeMap = new HashMap<>();
        CommonPageBuilder<MaterialQueryDTO, BaseMaterial> commonPageBuilder = new CommonPageBuilder<>(MaterialQueryDTO.class);
        commonPageBuilder.appendEntity(queryParams.getEntity())
                .appendQuery(queryParams.getQuery()).appendPage(queryParams.getPage());
        IPage<BaseMaterial> page = baseMaterialService.page(commonPageBuilder.bulid(), loginUser);
        List<BaseMaterial> Materials = page.getRecords();
        //结果对象
        IPage<MaterialVO> pageList = new Page<>();
        pageList.setTotal(page.getTotal());
        pageList.setCurrent(page.getCurrent());
        pageList.setSize(page.getSize());
        //查询到结果 数据转换
        if (ObjectUtil.isNotNull(Materials)) {
            pageList.setRecords(Materials.stream().map(baseMaterial -> {
                MaterialVO materialVO = new MaterialVO();
                BeanUtil.copyProperties(baseMaterial, materialVO);
                BaseMaterialType materialType = materialTypeMap.get(baseMaterial.getMaterialType());
                if(ObjectUtil.isNull(materialType)){
                    materialType = baseMaterialTypeService.queryMaterialTypeByMaterialTypeCode(baseMaterial.getMaterialType(),loginUser);
                    materialTypeMap.put(baseMaterial.getMaterialType(),materialType);
                }
                if(ObjectUtil.isNotNull(materialType)){
                    materialVO.setMaterialTypeName(materialType.getTypeName());
                }
                return materialVO;
            }).collect(Collectors.toList()));
        } else {
            pageList.setRecords(new ArrayList<>());
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, pageList);
    }

    /**
     * 查询物料列表信息--启用的物料
     *
     * @param queryParams
     * @return
     */
    @ServiceLog(name = "查询原料列表")
    public Result<List<MaterialVO>> queryMaterials(MaterialQueryParams queryParams) {
        Assert.notNull(queryParams, "参数[queryParams]不存在");
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        Map<String,BaseMaterialType> materialTypeMap = new HashMap<>();
        MaterialQueryDTO queryDTO = new MaterialQueryDTO();
        BeanUtil.copyProperties(queryParams, queryDTO);
        queryDTO.setStatus(YesOrNoEnum.YES.getValue());
        List<BaseMaterial> materials = baseMaterialService.list(queryDTO, loginUser);
        //查询对象
        List<MaterialVO> list = new ArrayList<>();
        if (ObjectUtil.isNotNull(materials)) {
            list = materials.stream().map(baseMaterial -> {
                MaterialVO materialVO = new MaterialVO();
                BeanUtil.copyProperties(baseMaterial, materialVO);
                BaseMaterialType materialType = materialTypeMap.get(baseMaterial.getMaterialType());
                if(ObjectUtil.isNull(materialType)){
                    materialType = baseMaterialTypeService.queryMaterialTypeByMaterialTypeCode(baseMaterial.getMaterialType(),loginUser);
                    materialTypeMap.put(baseMaterial.getMaterialType(),materialType);
                }
                if(ObjectUtil.isNotNull(materialType)){
                    materialVO.setMaterialTypeName(materialType.getTypeName());
                }
                return materialVO;
            }).collect(Collectors.toList());
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, list);
    }


    /**
     * 创建物料
     *
     * @param createParams 创建对象
     * @return Result
     */
    @Transactional
    @ServiceLog(name = "新增物料")
    public Result<String> createMaterial(MaterialCreateParams createParams) {
        ValidateUtil.validate(createParams);
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        //判断商品类型
        BaseMaterialType materialType = baseMaterialTypeService.queryMaterialTypeByMaterialTypeCode(createParams.getMaterialType(), loginUser);
        new MaterialTypeCheck(materialType).checkNull("物料类型错误");
        //判断MaterialName是否存在
        BaseMaterial baseMaterial = baseMaterialService.queryMaterialByMaterialName(createParams.getMaterialName(),loginUser);
        new MaterialCheck(baseMaterial).checkMaterialName(null, "物料名称已经存在");
        MaterialBuilder materialBuilder = new MaterialBuilder();
        materialBuilder.append(createParams)
                .appendStatus(YesOrNoEnum.YES.getValue()).appendCreate(loginUser);
        //保存物料信息
        if (!baseMaterialService.save(materialBuilder.bulid())) {
            log.info("保存物料接口异常,参数:{}", JSON.toJSONString(materialBuilder.bulid()));
            throw BusinessExceptionFactory.newException(MsgCodeConstant.Error.ERR00000001);
        }
        //查询信息 需要配置属性
        Map<String, String> tempMap = baseMaterialTemplateService.list(new MaterialTemplateQueryDTO(), loginUser)
                .stream().collect(Collectors.toMap(item -> item.getProp(), item -> item.getName()));
        List<String> existProp = new ArrayList<>();
        //保存扩展信息
        baseMaterialExtendService.saveBatch(createParams.getProps().stream().map(templateRecord -> {
            MaterialExtendBuilder materialInfoBuilder = new MaterialExtendBuilder();
            String name = tempMap.get(templateRecord.getProp());
            if(StrUtil.isBlank(name)){
                log.info("属性{}不存在",templateRecord.getProp());
                throw BusinessExceptionFactory.newException("属性不存在");
            }
            if(existProp.contains(templateRecord.getProp())){
                log.info("属性{}存在重复",templateRecord.getProp());
                throw BusinessExceptionFactory.newException("属性重复");
            }
            existProp.add(templateRecord.getProp());
            materialInfoBuilder.append(templateRecord).appendCode(materialBuilder.getCode())
                    .appendCompanyCode(loginUser.getCompanyCode()).appendName(name)
                    .appendCreate(loginUser);
            return materialInfoBuilder.bulid();
        }).collect(Collectors.toList()));
        //默认生成一条规格数据
        MaterialModelBuilder materialModelBuilder = new MaterialModelBuilder();
        materialModelBuilder.append(materialBuilder.bulid()).appendCreate(loginUser);
        materialModelService.save(materialModelBuilder.bulid());
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000001, materialBuilder.getCode());
    }


    /**
     * 编辑物料
     *
     * @param editParams 编辑对象
     * @return Result
     */
    @Transactional
    @ServiceLog(name = "编辑物料")
    public Result<String> editMaterial(MaterialEditParams editParams) {
        ValidateUtil.validate(editParams);
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        BaseMaterial existM  = baseMaterialService.queryMaterialByMaterialCode(editParams.getMaterialCode(),loginUser);
        new MaterialCheck(existM).checkNull("物料不存在");
        //判断MaterialKey是否存在
        BaseMaterial baseMaterial = baseMaterialService.queryMaterialByMaterialName(editParams.getMaterialName(),loginUser);
        new MaterialCheck(baseMaterial).checkMaterialName(editParams.getMaterialCode(), "物料名称已经存在");
        MaterialBuilder materialBuilder = new MaterialBuilder();
        materialBuilder.append(editParams).appendEdit(loginUser);
        //编辑物料信息
        if (!baseMaterialService.edit(materialBuilder.bulid(), loginUser)) {
            log.info("编辑物料接口异常,参数:{}", JSON.toJSONString(materialBuilder.bulid()));
            throw BusinessExceptionFactory.newException(MsgCodeConstant.Error.ERR00000001);
        }
        //判断类型是否变化 变更 更新规格
        if(!StrUtil.equals(editParams.getMaterialType(),existM.getMaterialType())){
            //更新数据
            materialModelService.updateMaterialType(editParams.getMaterialType(),existM.getMaterialCode(),loginUser);
        }
        //删除信息
        baseMaterialExtendService.deleteMaterialExtend(editParams.getMaterialCode(), loginUser);
        //查询信息 需要配置属性
        Map<String, String> tempMap = baseMaterialTemplateService.list(new MaterialTemplateQueryDTO(), loginUser)
                .stream().collect(Collectors.toMap(item -> item.getProp(), item -> item.getName()));

        List<String> existProp = new ArrayList<>();
        //保存扩展信息
        baseMaterialExtendService.saveBatch(editParams.getProps().stream().map(templateRecord -> {
            MaterialExtendBuilder materialInfoBuilder = new MaterialExtendBuilder();
            String name = tempMap.get(templateRecord.getProp());
            if(StrUtil.isBlank(name)){
                log.info("属性{}不在扩展中",templateRecord.getProp());
                throw BusinessExceptionFactory.newException("属性不存在");
            }
            if(existProp.contains(templateRecord.getProp())){
                log.info("属性{}存在重复",templateRecord.getProp());
                throw BusinessExceptionFactory.newException("属性重复");
            }
            existProp.add(templateRecord.getProp());
            materialInfoBuilder.append(templateRecord).appendCode(materialBuilder.getCode())
                    .appendCompanyCode(loginUser.getCompanyCode()).appendName(name)
                    .appendCreate(loginUser);
            return materialInfoBuilder.bulid();
        }).collect(Collectors.toList()));
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000001, materialBuilder.getCode());
    }


    /**
     * 删除物料
     *
     * @param materialCode 物料编码
     * @return Result
     */
    @Transactional
    @ServiceLog(name = "删除物料")
    public Result<String> deleteMaterial(String materialCode) {
        ValidateUtil.hasLength(materialCode, "参数[materialCode]不能为空");
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        //获取权限信息
        BaseMaterial baseMaterial = baseMaterialService.queryMaterialByMaterialCode(materialCode, loginUser);
        new MaterialCheck(baseMaterial).checkNull("物料不存在");
        MaterialBuilder MaterialBuilder = new MaterialBuilder();
        MaterialBuilder.appendCode(materialCode).appendEdit(loginUser).delete();
        //删除物料信息
        if (!baseMaterialService.edit(MaterialBuilder.bulid(), loginUser)) {
            log.info("删除物料接口异常,参数:{}", JSON.toJSONString(MaterialBuilder.bulid()));
            throw BusinessExceptionFactory.newException(MsgCodeConstant.Error.ERR00000001);
        }
        //删除物料相关 关联信息
        baseMaterialExtendService.deleteMaterialExtend(materialCode, loginUser);
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000001, MaterialBuilder.getCode());
    }

    /**
     * 开启物料
     *
     * @param materialCode 物料编码
     * @return Result
     */
    @Transactional
    @ServiceLog(name = "开启物料")
    public Result<String> openMaterial(String materialCode) {
        ValidateUtil.hasLength(materialCode, "参数[materialCode]不能为空");
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        //获取权限信息
        BaseMaterial baseMaterial = baseMaterialService.queryMaterialByMaterialCode(materialCode, loginUser);
        new MaterialCheck(baseMaterial).checkNull("物料不存在");
        MaterialBuilder MaterialBuilder = new MaterialBuilder();
        MaterialBuilder.appendCode(materialCode).appendEdit(loginUser).open();
        //开启物料信息
        if (!baseMaterialService.edit(MaterialBuilder.bulid(), loginUser)) {
            log.info("开启物料接口异常,参数:{}", JSON.toJSONString(MaterialBuilder.bulid()));
            throw BusinessExceptionFactory.newException(MsgCodeConstant.Error.ERR00000001);
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000001, MaterialBuilder.getCode());
    }

    /**
     * 关闭物料
     *
     * @param materialCode 物料编码
     * @return Result
     */
    @Transactional
    @ServiceLog(name = "关闭物料")
    public Result<String> closeMaterial(String materialCode) {
        ValidateUtil.hasLength(materialCode, "参数[materialCode]不能为空");
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        //获取权限信息
        BaseMaterial baseMaterial = baseMaterialService.queryMaterialByMaterialCode(materialCode, loginUser);
        new MaterialCheck(baseMaterial).checkNull("物料不存在");
        MaterialBuilder MaterialBuilder = new MaterialBuilder();
        MaterialBuilder.appendCode(materialCode).appendEdit(loginUser).close();
        //关闭物料信息
        if (!baseMaterialService.edit(MaterialBuilder.bulid(), loginUser)) {
            log.info("关闭物料接口异常,参数:{}", JSON.toJSONString(MaterialBuilder.bulid()));
            throw BusinessExceptionFactory.newException(MsgCodeConstant.Error.ERR00000001);
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000001, MaterialBuilder.getCode());
    }

    /**
     * 物料详情
     *
     * @param materialCode 物料编码
     * @return Result
     */
    @ServiceLog(name = "物料详情")
    public Result<MaterialVO> viewMaterial(String materialCode) {
        ValidateUtil.hasLength(materialCode, "参数[MaterialCode]不能为空");
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        //获取权限信息
        BaseMaterial baseMaterial = baseMaterialService.queryMaterialByMaterialCode(materialCode, loginUser);
        new MaterialCheck(baseMaterial).checkNull("物料不存在");
        MaterialVO materialVO = new MaterialVO();
        BeanUtil.copyProperties(baseMaterial, materialVO);
        //获取扩展信息
        Map<String, BaseMaterialExtend> extendMap = baseMaterialExtendService.listByMaterialCode(materialCode).stream()
                .collect(Collectors.toMap(item -> item.getProp(), item -> item));
        //获取属性信息
        List<PropVO> propVOS = baseMaterialTemplateService.listByComapnyCode(loginUser).stream().map(baseMaterialTemplate -> {
            return new PropBuilder().append(baseMaterialTemplate).append(extendMap.get(baseMaterialTemplate.getProp())).bulid();
        }).collect(Collectors.toList());
        materialVO.setProps(propVOS);
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, materialVO);
    }

}
